package digitRecognitionProblem.learnWeights;

import java.util.ArrayList;
import java.util.List;

import mlp.Layer;
import mlp.Mlp;
import mlp.MlpExamples;
import genetic_algorithm.Chromosome;

/**
 * A Chromosome holds an instance of a neural network.
 * The network's weights are the initial weights represented
 * by the chromosome 
 */
public class LWchromosome implements Chromosome {

	private Mlp mlp; // neural network represented by the chromosome
	
	/**
	 * Constructor- creates a new chromosome
	 * @param mlp data for the chromosome
	 */
	public LWchromosome(Mlp mlp) {
		super();
		this.mlp = mlp;
	}
	
	public Mlp getMlp() {
		return mlp;
	}
	
	public void setMlp(Mlp mlp) {
		this.mlp = mlp;
	}
	
	/**
	 * Returns index'th layer of chromosome's neural network
	 */
	@Override
	public Layer getValue(int index) throws IllegalArgumentException {

		// check boundaries
		if (index < 0 || index >= mlp.getNumLayers()) {
			return null;			
		}
		
		// return specified layer
		return mlp.getLayer(index);
	}
	
	/**
	 * Sets given layer as network's index'th layer
	 */
	@Override
	public void setValue(int index, Object obj) throws IllegalArgumentException {		
		mlp.setLayer(index, (Layer) obj);
	}
	
	/**
	 * Returns all layers of chromosome's neural network
	 */
	@Override
	public List<Object> getAllValues() {
		
		int numLayers = mlp.getNumLayers();
		List<Object> layers = new ArrayList<Object>(numLayers);
		for (int i = 0 ; i < numLayers ; ++i) {
			layers.add(mlp.getLayer(i));
		}

		return layers;
	}

	/**
	 * Measures chromosome's neural network's quadratic error
	 * on given test examples 
	 * @param testExamples examples used to measure network's performance
	 * @return neural network's quadratic error, normalized by number of
	 * test exmaples
	 */
	public float evaluateError(MlpExamples testExamples) {
		return mlp.evaluateQuadraticError(testExamples.getInput(),
				testExamples.getOutput())
				/ ((float) testExamples.getInput().size());
	}
	
	public String toString() {
		return mlp.toString();
	}
}
